﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using WinDocker.Common.Global;

namespace WinDocker.Common.Helper.Docker
{
    /// <summary>
    /// 外部服务进程调用处理类
    ///  实现热启动与热关闭.
    /// </summary>
    public class ServiceProcessDeal
    {
        private const string LOG_ERR_FILE = "LogErr.txt";
        private const string LOG_TRACE_FILE = "LogTrace.txt";
        public readonly static ServiceProcessDeal Instance = new ServiceProcessDeal();

        private bool Enable
        {
            get
            {
                var bRet = false;
                try
                {
                    var b = (Configs.GetAndAdd("IsServiceProcessDeal", "True").Trim().ToLower() == "true");
                    if (!b)
                    {
                        return bRet;
                    }
                    if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
                    {
                        return bRet;
                    }
                    bRet = true;
                }
                catch (Exception ex)
                {
                    LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal Enable Err:{ex.Message}");
                }
                return bRet;
            }
        }

        private string BaseDirectory = "";

        private string DirPath = "";

        private FileSystemWatcher Watcher = null;

        private ServiceProcessDeal()
        {
            try
            {
                this.BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
                LogWrite.PathHead = this.BaseDirectory;
                //LogWrite.TxtExport_DateNow("LogTest.txt", "D0");
                if (!this.Enable)
                {
                    return;
                }
                this.DirPath = $"{this.BaseDirectory}KnDService";
                this.GetPrograms();
                var dirPath = this.DirPath;
                if (!Directory.Exists(dirPath.GetRuntimeDirectoryByKND()))//若文件夹不存在则新建文件夹  
                {
                    Directory.CreateDirectory(dirPath.GetRuntimeDirectoryByKND()); //新建文件夹  
                }
                this.GetFolderPrograms();
                this.Watcher = new FileSystemWatcher();
                //实例化一个FileSystemWatcher对象
                var watcher = this.Watcher;
                // 设置要监控的文件夹路径
                watcher.Path = dirPath;//"C:\\MyFolder";
                                       //设置监控类型，包括文件重命名、创建、删除及文件夹重命名、创建、删除
                watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                                       | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                //添加文件变化事件处理程序
                //watcher.Changed += new FileSystemEventHandler(WatcherOnChanged);

                watcher.Created += this.WatcherEventMethod;

                //开始监控
                watcher.EnableRaisingEvents = true;
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal Err:{ex.Message}");
            }
        }

        private readonly object WatcherOnChangedLockObj = new object();
        private void WatcherOnChanged(object _source, FileSystemEventArgs _e)
        {
            try
            {
                System.Threading.Thread th = new System.Threading.Thread(oj =>
                {
                    lock (WatcherOnChangedLockObj)
                    {
                        try
                        {
                            var ojArray = (object[])oj;
                            var source = ojArray[0];
                            var e = (FileSystemEventArgs)ojArray[1];
                            //LogWrite.TxtExport_DateNow("LogTest.txt", $"\r\nFile：{e.FullPath}\r\nType:{e.ChangeType}\r\nName:{e.Name}\r\n");
                            if (e.FullPath.IndexOf("JtDFSer.json") < 0)
                            {
                                return;
                            }
                            Process process = null;
                            object[] obs = null;
                            var vls = this.DicProcess.Values;
                            if (vls.Any())
                            {
                                var vlsList = vls.Select(p => p).ToList();
                                foreach (var obs2 in vlsList)
                                {
                                    var watcher = obs2[2];
                                    if (watcher.Equals(source))
                                    {
                                        process = (Process)obs2[0];
                                        obs = (object[])obs2[1];
                                        break;
                                    }
                                }
                            }
                            var _path = "";
                            var _programFileName = "";
                            int _iPort = 0;
                            if (obs == null)
                            {
                                //return;
                                _path = Path.GetDirectoryName(e.FullPath);
                                _programFileName = _path.Split(Path.DirectorySeparatorChar).Last();
                                var split = '_';
                                var pnArray = _programFileName.Split(split);
                                if (pnArray.Length >= 2)
                                {
                                    _programFileName = pnArray[1];
                                }
                                if (pnArray.Length >= 3)
                                {
                                    if (int.TryParse(pnArray[2], out var i))
                                    {
                                        _iPort = i;
                                    }
                                }
                            }
                            else
                            {
                                _path = (string)obs[0];
                                _programFileName = (string)obs[1];
                                _iPort = (int)obs[2];
                            }

                            if (($"{_path}\\JtDFSer.json").GetRuntimeDirectoryByKND() != e.FullPath)
                            {
                                return;
                            }
                            var sPath = e.FullPath;//($"{e.FullPath}\\JtDFSer.json").GetRuntimeDirectoryByKND();
                            var bRun = false;
                            if (!File.Exists(sPath))
                            {
                                var ob = new { isRun = true };
                                var json = Tool.ConvertJsonString(Newtonsoft.Json.JsonConvert.SerializeObject(ob));
                                StreamWriter sw = new StreamWriter(sPath, false, Encoding.UTF8);   //该编码类型不会改变已有文件的编码类型
                                sw.WriteLine(json);
                                sw.Close();
                                //return;
                                bRun = ob.isRun;
                            }
                            else
                            {
                                StreamReader sr = new StreamReader(sPath, Encoding.UTF8);
                                string sRead = sr.ReadToEnd();
                                sr.Close();
                                Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(sRead);
                                var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(jo);
                                var dy = Tool.ToDynamicsByJson(json2).FirstOrDefault();
                                //LogWrite.TxtExport_DateNow("LogTest.txt", $"Dku:{dy.Get<string>("name")}");
                                if (dy != null)
                                {
                                    var b = dy.Get<bool?>("isRun");
                                    bRun = (b ?? false);
                                }
                            }
                            var hc = 0;
                            if (process != null)
                            {
                                hc = process.GetHashCode();
                            }
                            if (bRun)
                            {
                                this.ServiceProcessRun(_path, _programFileName, _iPort);
                            }
                            else
                            {
                                if (this.DicProcess.ContainsKey(hc))
                                {
                                    this.DicProcess.Remove(hc);
                                }
                                if (process != null)
                                {
                                    process.Kill();
                                    process = null;
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal WatcherOnChanged Err:{ex.Message}");
                        }
                    }
                });
                th.Start(new object[] { _source, _e });
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal WatcherOnChanged 0 Err:{ex.Message}");
            }
        }

        /// <summary>
        /// 文件(文件夹)事件处理程序(注:只能监控到监控目录下一级文件与文件夹的创建，子文件及子文件夹无法监控到)
        /// 业务规则:文件夹名称做特别约定,包含标识符、运行程序名(.用其它符号替代)、端口等信息
        ///          所述文件夹下新建个统一约定名称的配置文件,文件内容包含端口、启用或关停等设置信息，对该配置文件做好实时监控事件的处理.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void WatcherEventMethod(object source, FileSystemEventArgs e)
        {
            //Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
            //LogWrite.TxtExport_DateNow("LogTest.txt", $"\r\nFile:{e.FullPath}\r\nType:{e.ChangeType}\r\nName:{e.Name}\r\n");
            try
            {
                System.Threading.Thread th = new System.Threading.Thread((ob) =>
                {
                    try
                    {
                        var _e = (FileSystemEventArgs)ob;
                        var path = _e.FullPath;
                        if (!Path.HasExtension(path))//非文件夹,退出
                        {
                            return;
                        }
                        var pathName = (_e.Name ?? "").Trim();
                        var sTag = "JtDFSer";//起始标识符
                        if (pathName.IndexOf(sTag) != 0)//非约定好的文件夹名,退出
                        {
                            return;
                        }

                        var sPath = ($"{e.FullPath}\\JtDFSer.json").GetRuntimeDirectoryByKND();
                        //var bRun = false;
                        if (!File.Exists(sPath))
                        {
                            var obj = new { isRun = true };
                            var json = Tool.ConvertJsonString(Newtonsoft.Json.JsonConvert.SerializeObject(obj));
                            StreamWriter sw = new StreamWriter(sPath, false, Encoding.UTF8);   //该编码类型不会改变已有文件的编码类型
                            sw.WriteLine(json);
                            sw.Close();
                            //return;
                            //bRun = ob.isRun;
                        }

                        System.Threading.Thread.Sleep(15 * 1000);//注：延时一下，等待文件拷贝完.默认延时15秒.
                        var splitTag = '_';//分割符
                        var pnArray = pathName.Split(splitTag);
                        var programFileName = "";//运行程序名
                        if (pnArray.Length >= 2)
                        {
                            programFileName = pnArray[1];
                            //var dotChar = "。";//.符号替换符
                            //programFileName = programFileName.Replace(dotChar, ".");
                        }
                        int iPort = 0;//端口
                        if (pnArray.Length >= 3)
                        {
                            int.TryParse(pnArray[2], out iPort);
                        }
                        this.ServiceProcessRun(path, programFileName, iPort);
                    }
                    catch (Exception ex)
                    {
                        LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal WatcherEventMethod 0Err:{ex.Message}");
                    }
                });
                th.Start(e);
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal WatcherEventMethod Err:{ex.Message}");
            }
        }

        /// <summary>
        /// 进程对像哈希表
        /// 《进程对像哈希值，object[]{ Process对像, object[]{ string path, string programFileName, int iPort} }》
        /// </summary>
        private Dictionary<int, object[]> DicProcess = new Dictionary<int, object[]>();

        private void ServiceProcessRun(string path, string programFileName, int iPort)
        {
            try
            {
                //Process process = null;
                string exeFilePath = ($"{path}\\{programFileName}").GetRuntimeDirectoryByKND();

                var vls = this.DicProcess.Values;
                if (vls.Any())
                {
                    var vlsList = vls.Select(p => p).ToList();
                    foreach (var obs2 in vlsList)
                    {
                        var process2 = (Process)obs2[0];
                        var obs2Array = (object[])obs2[1];
                        var exeFp = ($"{(string)(obs2Array[0])}\\{(string)(obs2Array[1])}").GetRuntimeDirectoryByKND();
                        if (/*process2.StartInfo.FileName*/exeFp == exeFilePath)
                        {
                            LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"已运行的进程:{exeFilePath}");
                            return;
                        }
                    }
                }

                string exeWorkingDirectory = path;
                var info = new ProcessStartInfo();
                info.WorkingDirectory = exeWorkingDirectory;
                info.FileName = exeFilePath;
                if (iPort > 0)
                {
                    info.Arguments = $"{iPort}";
                }

                var args = "";
                try
                {
                    var sPath = ($"{path}\\JtDFSer.json").GetRuntimeDirectoryByKND();
                    if (File.Exists(sPath))
                    {
                        StreamReader sr = new StreamReader(sPath, Encoding.UTF8);
                        string sRead = sr.ReadToEnd();
                        sr.Close();
                        Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(sRead);
                        var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(jo);
                        var dy = Tool.ToDynamicsByJson(json2).FirstOrDefault();
                        //LogWrite.TxtExport_DateNow("LogTest.txt", $"Dku:{dy.Get<string>("name")}");
                        if (dy != null)
                        {
                            args = (dy.Get<string>("prArgs") ?? "").Trim();
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal ServiceProcessRun 362Err:{ex.Message}");
                }
                if (args != "")
                {
                    info.Arguments = $"{args}";
                }

                var process = Process.Start(info);
                var hc = process.GetHashCode();

                //实例化一个FileSystemWatcher对象
                var watcher = new FileSystemWatcher();
                // 设置要监控的文件夹路径
                watcher.Path = path;//"C:\\MyFolder";
                                    //设置监控类型，包括文件重命名、创建、删除及文件夹重命名、创建、删除
                watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                                       | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                //添加文件变化事件处理程序
                watcher.Changed += new FileSystemEventHandler(WatcherOnChanged);
                //开始监控
                watcher.EnableRaisingEvents = true;

                var obs = new object[] { process, new object[] { path, programFileName, iPort }, watcher };
                if (this.DicProcess.ContainsKey(hc))
                {
                    this.DicProcess[hc] = obs;
                }
                else
                {
                    this.DicProcess.Add(hc, obs);
                }
                process.EnableRaisingEvents = true;
                process.Exited += ((s, e) =>
                {
                    try
                    {
                        ////LogWrite.TxtExport_DateNow("LogTestExit.txt", "D2");
                        //if (this.IsStop)
                        //{
                        //    return;
                        //}
                        ////LogWrite.TxtExport_DateNow("LogTestExit.txt", "D3");
                        //this.process = null;
                        //this.DFProcessRun(this.BaseDirectory);

                        var prc = (Process)s;
                        var _hc = prc.GetHashCode();
                        if (!this.DicProcess.ContainsKey(_hc))
                        {
                            LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"停止了进程:{/*prc.MainModule.FileName*/_hc}");
                            return;
                        }
                        var _obs = this.DicProcess[_hc];
                        var obsParam = (object[])_obs[1];
                        var _path = (string)obsParam[0];
                        var _programFileName = (string)obsParam[1];
                        var _iPort = (int)obsParam[2];
                        this.DicProcess.Remove(_hc);
                        this.ServiceProcessRun(_path, _programFileName, _iPort);
                    }
                    catch (Exception ex)
                    {
                        LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal ServiceProcessRun 0Err:{ex.Message}");
                    }
                });
                LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"运行了进程:{process.StartInfo.FileName}");
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal ServiceProcessRun Err:{ex.Message}");
            }
        }

        public void Start()
        {
            try
            {
                //LogWrite.TxtExport_DateNow("LogTest.txt", "D1");
                if (!this.Enable)
                {
                    return;
                }
                //this.GetPrograms();
                //this.Test();
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal Start Err:{ex.Message}");
            }
        }

        private void GetPrograms()
        {
            try
            {
                var prcList = Process.GetProcesses();
                foreach (var process in prcList)
                {
                    try
                    {
                        var module = process.MainModule;
                        var path = module.FileName;//Path.Combine(module.BaseAddress, module.FileName);
                                                   //Console.WriteLine($"进程名称: {process.ProcessName}, 运行路径: {path}");
                                                   //if (path.IndexOf("FastTunnel.Client") >= 0)
                                                   //{
                                                   //    var ii = 9;
                                                   //}
                        if (path.IndexOf(this.DirPath) != 0)
                        {
                            continue;
                        }
                        var hc = process.GetHashCode();
                        //int iPort = 0;
                        //if (int.TryParse(process.StartInfo.Arguments, out var i))
                        //{
                        //    iPort = i;
                        //}

                        var __path = "";
                        var __programFileName = "";
                        int __iPort = 0;
                        __path = Path.GetDirectoryName(path);
                        __programFileName = __path.Split(Path.DirectorySeparatorChar).Last();
                        var split = '_';
                        var pnArray = __programFileName.Split(split);
                        if (pnArray.Length >= 2)
                        {
                            __programFileName = pnArray[1];
                        }
                        if (pnArray.Length >= 3)
                        {
                            if (int.TryParse(pnArray[2], out var i))
                            {
                                __iPort = i;
                            }
                        }


                        //实例化一个FileSystemWatcher对象
                        var watcher = new FileSystemWatcher();
                        // 设置要监控的文件夹路径
                        watcher.Path = __path;//"C:\\MyFolder";
                                              //设置监控类型，包括文件重命名、创建、删除及文件夹重命名、创建、删除
                        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                                               | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                        //添加文件变化事件处理程序
                        watcher.Changed += new FileSystemEventHandler(WatcherOnChanged);
                        //开始监控
                        watcher.EnableRaisingEvents = true;

                        var obs = new object[] { process, new object[] { __path, __programFileName, __iPort }, watcher };
                        if (this.DicProcess.ContainsKey(hc))
                        {
                            this.DicProcess[hc] = obs;
                        }
                        else
                        {
                            this.DicProcess.Add(hc, obs);
                        }

                        process.EnableRaisingEvents = true;
                        process.Exited += ((s, e) =>
                        {
                            try
                            {
                                var prc = (Process)s;
                                var _hc = prc.GetHashCode();
                                //var _obs = this.DicProcess[_hc];
                                //var obsParam = (object[])_obs[1];
                                //var _path = (string)obsParam[0];
                                //var _programFileName = (string)obsParam[1];
                                //var _iPort = (int)obsParam[2];
                                if (!this.DicProcess.ContainsKey(_hc))
                                {
                                    LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"停止了进程：{/*prc.MainModule.FileName*/_hc}");
                                    return;
                                }
                                var _obs = this.DicProcess[_hc];
                                var obsParam = (object[])_obs[1];
                                var _path = (string)obsParam[0];
                                var _programFileName = (string)obsParam[1];
                                var _iPort = (int)obsParam[2];
                                this.DicProcess.Remove(_hc);
                                this.ServiceProcessRun(_path, _programFileName, _iPort);
                            }
                            catch (Exception ex)
                            {
                                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal GetPrograms 00Err:{ex.Message}");
                            }
                        });
                        LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"获取了进程:{__path}|{__programFileName}");
                    }
                    catch (Exception ex)
                    {
                        LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal GetPrograms 0Err:{ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal GetPrograms Err:{ex.Message}");
            }
        }

        private void GetFolderPrograms()
        {
            try
            {
                var path = this.DirPath;
                //var dir = new DirectoryInfo(path);
                var dirs = Directory.GetDirectories(path);
                if ((dirs == null) || (!dirs.Any()))
                {
                    return;
                }

                foreach (var d in dirs)
                {
                    try
                    {
                        var _path = "";
                        var _programFileName = "";
                        int _iPort = 0;
                        _path = d;//Path.GetDirectoryName(d);
                        _programFileName = _path.Split(Path.DirectorySeparatorChar).Last();
                        var split = '_';
                        var pnArray = _programFileName.Split(split);
                        if (pnArray.Length >= 2)
                        {
                            _programFileName = pnArray[1];
                        }
                        if (pnArray.Length >= 3)
                        {
                            if (int.TryParse(pnArray[2], out var i))
                            {
                                _iPort = i;
                            }
                        }
                        var bRun = true;
                        var sPath = ($"{_path}\\JtDFSer.json").GetRuntimeDirectoryByKND();
                        if (File.Exists(sPath))
                        {
                            StreamReader sr = new StreamReader(sPath, Encoding.UTF8);
                            string sRead = sr.ReadToEnd();
                            sr.Close();
                            Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(sRead);
                            var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(jo);
                            var dy = Tool.ToDynamicsByJson(json2).FirstOrDefault();
                            //LogWrite.TxtExport_DateNow("LogTest.txt", $"Dku:{dy.Get<string>("name")}");
                            if (dy != null)
                            {
                                var b = dy.Get<bool?>("isRun");
                                bRun = (b ?? false);
                            }
                        }
                        LogWrite.TxtExport_DateNow(LOG_TRACE_FILE, $"{(bRun ? "从已有文件夹启动了进程" : "已有文件夹被设置成禁用启动进程")}:{_path}|{_programFileName}");
                        if (!bRun)
                        {
                            //实例化一个FileSystemWatcher对象
                            var watcher = new FileSystemWatcher();
                            // 设置要监控的文件夹路径
                            watcher.Path = _path;//"C:\\MyFolder";
                                                 //设置监控类型，包括文件重命名、创建、删除及文件夹重命名、创建、删除
                            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                                                   | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                            //添加文件变化事件处理程序
                            watcher.Changed += new FileSystemEventHandler(WatcherOnChanged);
                            //开始监控
                            watcher.EnableRaisingEvents = true;
                            //return;
                        }
                        else
                        {
                            this.ServiceProcessRun(_path, _programFileName, _iPort);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal GetFolderPrograms 0Err:{ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal GetFolderPrograms Err:{ex.Message}");
            }
        }

        private void Test()
        {
            try
            {
                var sPath = $"{this.DirPath}\\TestF\\TestJ.json";
                if (!File.Exists(sPath))
                {
                    var ob = new { uid = "KnD001", dt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), name = "小狄测试01", sex = 0 };
                    var json = Tool.ConvertJsonString(Newtonsoft.Json.JsonConvert.SerializeObject(ob));
                    StreamWriter sw = new StreamWriter(sPath, false, Encoding.UTF8);   //该编码类型不会改变已有文件的编码类型
                    sw.WriteLine(json);
                    sw.Close();
                    return;
                }
                StreamReader sr = new StreamReader(sPath, Encoding.UTF8);
                string sRead = sr.ReadToEnd();
                sr.Close();
                Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(sRead);
                var json2 = Newtonsoft.Json.JsonConvert.SerializeObject(jo);
                var dy = Tool.ToDynamicsByJson(json2).FirstOrDefault();
                LogWrite.TxtExport_DateNow("LogTest.txt", $"Dku:{dy.Get<string>("name")}");
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow(LOG_ERR_FILE, $"ServiceProcessDeal Test Err:{ex.Message}");
            }
        }

    }

    static class SPDSupplement
    {
        public static string GetRuntimeDirectoryByKND(this string str)
        {
            return str;
        }
    }
}
